/*
    Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "Monster.h"
#include <stdlib.h>
#include "MonsterDate.h"
#include "MonsterState.h"
#include "Event.h"
#include <set>
#define random(x) (rand() % x)

#define FORVER_TIMES 1000
#define DEFAULT_X 200
#define DEFAULT_Y 200
#define DEFAULT_W 50
#define DEFAULT_H 20

#define DEFAULT_SKILL_LEN 110 //技能的探测线长度

static std::wstring MOVE_TO_ACTION_KEY = L"{D94A873D-C138-42B4-A83B-B17DE53EADFD}";
static std::wstring MOVE_ANIMATION_NAME = L"{D5FC2C16-BEF5-4AB0-9499-FD2E8A3DD9AF}";
static std::wstring ATTACK_ANIMATION_NAME = L"{334C8968-D1F8-4851-B8A2-63572932B0B0}";
static std::wstring DAMAGE_ANIMATION_NAME = L"{0E6BF273-36BB-442D-89AC-F804374D641A}";

static int s_skill_audio_id = -1;

//{{ 不同的小怪 动画资源不同

#define GET_ANIMATION(type_name) \
    const AnimationSharedPtr &getAnimation##type_name() { return m_animation##type_name; }

#define GET_INSTANCE(class_name)     \
public:                              \
    static class_name *getInstance() \
    {                                \
        static class_name a;         \
        return &a;                   \
    }                                \
                                     \
private:

class MosterAnimation
{
public:
    virtual ~MosterAnimation() = default;

    GET_ANIMATION(Death)
    GET_ANIMATION(Attack)
    GET_ANIMATION(Move)
    GET_ANIMATION(Damage)

protected:
    MosterAnimation() = default;

    AnimationSharedPtr m_animationDeath;  //死亡的动画
    AnimationSharedPtr m_animationAttack; //攻击的动画
    AnimationSharedPtr m_animationMove;   //走动的动画
    AnimationSharedPtr m_animationDamage; //受伤的动画
};

class MonsterAAnimationFactor final
    : public MosterAnimation
{
    GET_INSTANCE(MonsterAAnimationFactor)
private:
    MonsterAAnimationFactor()
    {
        auto cache = GameWorld::getInstance()->getDefultSpriteFrameCache();
        std::vector<SpriteFrameSharedPtr> frames;

        //走路
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy1-1-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-1-2"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-1-3"));
        m_animationMove = Animation::create(frames, 0.2f, 1000);
        m_animationMove->setRestOriginalFrame(true);
        //攻击
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy1-2-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-2-2"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-2-3"));
        m_animationAttack = Animation::create(frames, 0.2f);
        m_animationAttack->setRestOriginalFrame(true);
        //死亡
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy1-3-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-3-2"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-3-3"));
        m_animationDeath = Animation::create(frames, 0.2f);
        m_animationDeath->setRestOriginalFrame(false);
        //受伤
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy1-4-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy1-4-2"));
        m_animationDamage = Animation::create(frames, 0.15f);
        m_animationDamage->setRestOriginalFrame(true);
    }
};

class MonsterBAnimationFactor final
    : public MosterAnimation
{
    GET_INSTANCE(MonsterBAnimationFactor)
private:
    MonsterBAnimationFactor()
    {
        auto cache = GameWorld::getInstance()->getDefultSpriteFrameCache();
        std::vector<SpriteFrameSharedPtr> frames;

        //走路
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy2-1-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-1-2"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-1-3"));
        m_animationMove = Animation::create(frames, 0.2f, 1000);
        m_animationMove->setRestOriginalFrame(true);
        //攻击
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy2-2-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-2-2"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-2-3"));
        m_animationAttack = Animation::create(frames, 0.2f);
        m_animationAttack->setRestOriginalFrame(true);
        //死亡
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy2-3-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-3-2"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-3-3"));
        m_animationDeath = Animation::create(frames, 0.2f);
        m_animationDeath->setRestOriginalFrame(false);
        //受伤
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"enemy2-4-1"));
        frames.push_back(cache->getSpriteFrame(L"enemy2-4-2"));
        m_animationDamage = Animation::create(frames, 0.15f);
        m_animationDamage->setRestOriginalFrame(true);
    }
};

class MonsterBoosAnimationFactor final
    : public MosterAnimation
{
    GET_INSTANCE(MonsterBoosAnimationFactor)
private:
    MonsterBoosAnimationFactor()
    {
        auto cache = GameWorld::getInstance()->getDefultSpriteFrameCache();
        std::vector<SpriteFrameSharedPtr> frames;

        //走路
        frames.clear();
        m_animationMove = Animation::create(frames, 0.2f, 0);
        m_animationMove->setRestOriginalFrame(true);
        //攻击
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"df1-2-1"));
        frames.push_back(cache->getSpriteFrame(L"df1-2-2"));
        frames.push_back(cache->getSpriteFrame(L"df1-2-3"));
        frames.push_back(cache->getSpriteFrame(L"df1-2-4"));
        frames.push_back(cache->getSpriteFrame(L"df1-2-5"));
        frames.push_back(cache->getSpriteFrame(L"df1-2-1"));
        m_animationAttack = Animation::create(frames, 0.2f);
        m_animationAttack->setRestOriginalFrame(true);
        //死亡
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"df1-3-1"));
        frames.push_back(cache->getSpriteFrame(L"df1-3-2"));
        frames.push_back(cache->getSpriteFrame(L"df1-3-3"));
        frames.push_back(cache->getSpriteFrame(L"df1-3-4"));
        m_animationDeath = Animation::create(frames, 0.2f);
        m_animationDeath->setRestOriginalFrame(false);
        //受伤
        frames.clear();
        frames.push_back(cache->getSpriteFrame(L"df1-4-1"));
        frames.push_back(cache->getSpriteFrame(L"df1-4-2"));
        m_animationDamage = Animation::create(frames, 0.15f);
        m_animationDamage->setRestOriginalFrame(true);
    }
};

//}}

//----------------------------------------------------------------------//

void Monster::initAudio()
{
    s_skill_audio_id = AudioManager::getInstance()->loadAudio(_R("skill_moster.mp3"));
}

Monster::Monster()
    : m_monsterDate(nullptr), m_isMoving(false), m_spDirect(IPlayer::Direction::Left), m_isAttacking(false), m_attackTarget(nullptr), m_scene(nullptr), m_id(-1), m_isPlayDamageAnimation(false), m_isDeath(false), m_isDebug(false)
{
}

bool Monster::init(MonsterType type, Node *parent, IGameLevelScene *g)
{
    m_scene = g;
    m_id = m_scene->allocateRectId();
    this->setId(m_id);

    m_monsterType = type;
    auto cache = GameWorld::getInstance()->getDefultSpriteFrameCache();

    //初始化精灵
    SpriteFrameSharedPtr sf = nullptr;
    switch (type)
    {
    case IMonster::MonsterType::MonsterTypeA:
    {
        m_monsterDate = new MonsterDateA();
        sf = cache->getSpriteFrame(L"enemy1-1-1");
        break;
    }
    case IMonster::MonsterType::MonsterTypeB:
    {
        m_monsterDate = new MonsterDateB();
        sf = cache->getSpriteFrame(L"enemy2-1-1");
        break;
    }
    case IMonster::MonsterType::MosterTypeBoos:
    {
        m_monsterDate = new MonsterDateBoos();
        sf = cache->getSpriteFrame(L"df1-1-1");
        break;
    }
    default:
        return false;
    }
    m_playerSp = Sprite::create(sf, parent);

#if 0

	int r = random(13);
	int rr = random(12);

	int r_d = random(1000);
	if (r_d < 300)
	{
		m_playerSp->setPosition(900 + 10 * rr, r * 30);
		m_lastPos = m_playerSp->getPosition();
	}
	else if (r_d < 600)
	{
		m_playerSp->setPosition(50 + 10 * rr, 37 + r * 30);
		m_lastPos = m_playerSp->getPosition();
	}
	else if (r_d < 700)
	{
		m_playerSp->setPosition(120 + 35 * rr, 40 + r * 21);
		m_lastPos = m_playerSp->getPosition();
	}
	else
	{
		m_playerSp->setPosition(700 + 20 * rr, 30 + r * 16);
		m_lastPos = m_playerSp->getPosition();
	}

#else

    int x = random(1300);
    int y = random(480);
    m_playerSp->setPosition(x, y);
    m_lastPos = m_playerSp->getPosition();
#endif

    //初始化血量
    m_hp = m_monsterDate->getTotalHp();

    //初始化动画
    if (!this->initAnimation())
    {
        return false;
    }

    if (!this->initShape())
    {
        return false;
    }

    //初始化人物血条
    m_hpProgressBar = ProgressBar::create();
    m_hpProgressBar->setBackgroundImage(
        std::unique_ptr<Scale9Image>(
            Scale9Image::create(cache->getSpriteFrame(L"small-enemy-progress-bg"), Rect::Zero)));

    auto fill_sf = cache->getSpriteFrame(L"small-enemy-progress-fill");
    auto fill_rect = fill_sf->getRect();

    m_hpProgressBar->setFillImage(
        std::unique_ptr<Scale9Image>(
            Scale9Image::create(fill_sf, Rect(0, 0, fill_rect.getWidth() - 6, fill_rect.getHeight() - 6))));

    m_hpProgressBar->resize(Size(100, 20));
    auto pos = m_playerSp->getPosition();
    m_hpProgressBar->move(pos.x, pos.y + 80);
    m_hpProgressBar->setPadding(5, 5, 5, 5);
    m_hpProgressBar->setMaxValue(m_monsterDate->getTotalHp());
    m_hpProgressBar->setCurrentValue(m_monsterDate->getTotalHp());

    //初始化人物 受伤时的血量显示
    m_hurtNumberLabel = Label::create();
    m_hurtNumberLabel->move(pos.x, pos.y + 90);
    m_hurtNumberLabel->setFont(Font(L"方正舒体", 23, Font::FONT_WEIGHT::FONT_WEIGHT_BOLD));
    m_hurtNumberLabel->hide();

    //初始化状态机
    m_machine = std::make_unique<MonsterMachine>(g, this);
    m_machine->changeState(new MigrationState());

    //注册人物发生移动的监听
    m_playerSp->installListenerAtPosChangeBefore(std::bind(&Monster::onPlayerMoveBefore, this, std::placeholders::_1));
    m_playerSp->installListenerAtPosChangeAfter(
        std::bind(&Monster::onPlayerMoveAfter, this, std::placeholders::_1, std::placeholders::_2));

    m_debugEventHandle = GameWorld::getInstance()->getEventManager()->addListener<DebugEvent>([this](Event *e)
                                                                                              {
		auto event = dynamic_cast<DebugEvent*>(e);
		if (event)
		{
			m_isDebug = event->isDebug();
		} });

    return true;
}

void Monster::stand()
{
    if (m_isMoving)
    {
        this->stopMoveAnimation();
        m_playerSp->stopActionByName(MOVE_TO_ACTION_KEY);
        m_isMoving = false;
    }

    if (m_isAttacking)
    {
        this->stopAttackAnimation();
        m_isAttacking = false;
    }
}

void Monster::attack(IPlayer *player)
{
    if (m_isAttacking)
    {
        return;
    }

    if (m_isPlayDamageAnimation)
    {
        this->stopDamageAnimation();
    }

    m_attackTarget = player;
    this->playAttackAnimation();
    m_isAttacking = true;
}

bool Monster::canAttack(const Rect &main_player_rect)
{
    return main_player_rect.intersectWithLine(m_skillLine);
}

void Monster::moveTo(const Vector2 &pos)
{
    if (m_isPlayDamageAnimation)
    {
        this->stopDamageAnimation();
    }

    //开启动画
    if (!m_isMoving)
    {
        this->playMoveAnimation();
        m_isMoving = true;
    }

    //计算朝向
    auto target_pos = pos;
    auto self_pos = m_playerSp->getPosition();

    float b = target_pos.x - self_pos.x;
    if (b <= 0)
    { //左边
        m_playerSp->setFlipV(false);
        if (m_spDirect == IPlayer::Direction::Right)
        {
            m_playerSp->movePosition(-80, 0);

            auto shep_rect = m_monsterDate->getShapeRect();
            m_shapeLeft = m_playerSp->getPosition().x - shep_rect.getLeft();
            m_playerRect.moveTo(m_shapeLeft, m_playerRect.getBottom());

            m_skillLine.startPos.x = m_playerRect.getLeft();
            m_skillLine.endPos.x = m_skillLine.startPos.x + m_playerRect.getWidth() - m_monsterDate->getAttackDistance();
            m_spDirect = IPlayer::Direction::Left;
            m_hpProgressBar->move(m_hpProgressBar->getPosition() + Vector2(100, 0));
        }
    }
    else
    { //右边
        m_playerSp->setFlipV(true);
        if (m_spDirect == IPlayer::Direction::Left)
        {
            m_playerSp->movePosition(80, 0);

            auto shep_rect = m_monsterDate->getShapeRect();
            m_shapeLeft = m_playerSp->getPosition().x - (shep_rect.getWidth() - shep_rect.getLeft());
            m_playerRect.moveTo(m_shapeLeft, m_playerRect.getBottom());

            m_skillLine.startPos.x = m_playerRect.getLeft() + m_playerRect.getWidth();
            m_skillLine.endPos.x = m_skillLine.startPos.x - m_playerRect.getWidth() + m_monsterDate->getAttackDistance();
            m_spDirect = IPlayer::Direction::Right;
            m_hpProgressBar->move(m_hpProgressBar->getPosition() - Vector2(100, 0));
        }
    }

    //先停止原来的
    m_playerSp->stopActionByName(MOVE_TO_ACTION_KEY);

    //开始一个新的
    float d = Vector2::distance(pos, m_playerSp->getPosition());
    float speed = m_monsterDate->getSpeed();
    float time = d / speed;
    auto action = ActionMove::createMoveToTargetPos(pos.x, pos.y, time);
    action->setName(MOVE_TO_ACTION_KEY);
    m_playerSp->runAction(action->convertToActionSharedPtr());
}

void Monster::run(float dt)
{
    if (m_isDebug)
    {
        auto p = GameWorld::getInstance()->getRenderInterface();
        Geometry::drawRect(p, m_playerRect, Color4f::Red);
        Geometry::drawLine(p, m_skillLine.startPos, m_skillLine.endPos, Color4f::Blue);
    }
}

MonsterMachine *Monster::getMonsterMachine()
{
    return m_machine.get();
}

void Monster::modifyHp(int dt, ModifyHpType type)
{
    if (this->isDeath())
    {
        return;
    }

    int tmp = m_hp;

    m_hp += dt;
    if (m_hp < 0)
    {
        m_hp = 0;
    }
    else if (m_hp > m_monsterDate->getTotalHp())
    {
        m_hp = m_monsterDate->getTotalHp();
    }

    if (tmp > m_hp)
    {
        if (type == IPlayer::ModifyHpType::Nomale)
        {
            m_hurtNumber = std::to_wstring(tmp - m_hp);
            m_hurtNumberLabel->setTextColor(Color4f::White);
        }
        else if (type == IPlayer::ModifyHpType::Critical)
        {
            m_hurtNumber = std::wstring(L"暴击") + std::to_wstring(tmp - m_hp);
            m_hurtNumberLabel->setTextColor(Color4f::Red);
        }

        m_hurtNumberLabel->setText(m_hurtNumber);
        m_hurtNumberLabel->show();
        auto pos = m_hurtNumberLabel->getAbsPos() + Vector2(10, 10);
        auto move_action = ActionMove::createMoveToTargetPos(pos.x, pos.y, 0.6);

        auto call = ActionCallFunction::create([this]()
                                               { m_hurtNumberLabel->hide(); });

        ActionSequence::create(
            move_action->convertToActionTimeSharedPtr(),
            call->convertToActionTimeSharedPtr())
            ->runWithTarget(m_hurtNumberLabel);
    }

    this->onHpChange(tmp, m_hp);

    if (m_hp <= 0)
    {
        this->onPlayerDeath();
    }
}

int Monster::getCurrentHp() const
{
    return m_hp;
}

bool Monster::isDeath() const
{
    return m_isDeath;
}

Rect Monster::getRect()
{
    return m_playerRect;
}

Vector2 Monster::getPosition()
{
    return Vector2(m_playerSp->getPosition().x, m_playerRect.getBottom());
}

int Monster::getMaxHp() const
{
    return m_monsterDate->getTotalHp();
}

void Monster::setOrder(int order)
{
    m_playerSp->setLoacalZOrder(order);
}

void Monster::Bruise()
{
    this->playerDamageAnimation();
}

void Monster::notifyMiss()
{
}

bool Monster::initAnimation()
{
    switch (m_monsterType)
    {
    case IMonster::MonsterType::MonsterTypeA:
    {
        m_animationMove = MonsterAAnimationFactor::getInstance()->getAnimationMove();
        m_animationAttack = MonsterAAnimationFactor::getInstance()->getAnimationAttack();
        m_animationDeath = MonsterAAnimationFactor::getInstance()->getAnimationDeath();
        m_animationDamage = MonsterAAnimationFactor::getInstance()->getAnimationDamage();
        break;
    }
    case IMonster::MonsterType::MonsterTypeB:
    {
        m_animationMove = MonsterBAnimationFactor::getInstance()->getAnimationMove();
        m_animationAttack = MonsterBAnimationFactor::getInstance()->getAnimationAttack();
        m_animationDeath = MonsterBAnimationFactor::getInstance()->getAnimationDeath();
        m_animationDamage = MonsterBAnimationFactor::getInstance()->getAnimationDamage();
        break;
    }
    case IMonster::MonsterType::MosterTypeBoos:
    {
        m_animationMove = MonsterBoosAnimationFactor::getInstance()->getAnimationMove();
        m_animationAttack = MonsterBoosAnimationFactor::getInstance()->getAnimationAttack();
        m_animationDeath = MonsterBoosAnimationFactor::getInstance()->getAnimationDeath();
        m_animationDamage = MonsterBoosAnimationFactor::getInstance()->getAnimationDamage();
        break;
    }
    default:
        return false;
    }
    return true;
}

bool Monster::initShape()
{
    //初始化矩形表示
    auto rect = m_monsterDate->getShapeRect();

    m_shapeBottom = m_playerSp->getPosition().y - rect.getBottom();
    m_shapeLeft = m_playerSp->getPosition().x - rect.getLeft();

    m_playerRect = Rect(m_shapeLeft, m_shapeBottom, rect.getWidth(), rect.getHeight());

    //初始化探测线
    m_skillLine = Line(m_shapeLeft, m_shapeBottom + rect.getHeight() / 2, m_shapeLeft + rect.getWidth() - m_monsterDate->getAttackDistance(), m_shapeBottom + rect.getHeight() / 2);

    if (m_scene)
    {
        m_scene->modifyRectById(m_id, m_playerRect);
    }

    return true;
}

void Monster::onAttackFinish()
{
    DebugInfor("attack finish");
    if (m_attackTarget)
    {
        if (m_attackTarget->getRect().intersectWithLine(m_skillLine))
        {
            bool is_critical = random(1000) < 1000 * m_monsterDate->getCritical();
            int h = is_critical ? m_monsterDate->getNormalDamage() * 2 : m_monsterDate->getNormalDamage();
            m_attackTarget->modifyHp(-h, is_critical ? IPlayer::ModifyHpType::Critical : IPlayer::ModifyHpType::Nomale);
        }
        else
        {
            m_attackTarget->notifyMiss();
        }
    }

    m_isAttacking = false;

    this->getMonsterMachine()->changeState(new MoveToMainPlayer());
}

void Monster::onHpChange(int old, int now)
{
    //更新一下小怪的血条
    m_hpProgressBar->setCurrentValue(m_hp);

    // 死了就不要再进行受伤状态了
    if (m_hp == 0)
    {
        return;
    }

    //受伤了
    if (old > now)
    {
        this->playerDamageAnimation();

        this->getMonsterMachine()->changeState(new BruiseState);
    }
}

void Monster::onPlayerDeath()
{
    m_isDeath = true;

    //清空状态
    getMonsterMachine()->stop();

    //播放动画
    this->playDeathAnimation();

    int x = 0;
    if (m_spDirect == IPlayer::Direction::Left)
    {
        x = 50;
    }
    else
    {
        x = -50;
    }
    auto pos = m_hpProgressBar->getAbsPos() - Vector2(x, 50);

    ActionMove::createMoveToTargetPos(pos.x, pos.y, 0.6)->runWithTarget(m_hpProgressBar);
    if (m_isMoving)
    {
        ActionManager::getInstance()->removeActionByName(MOVE_TO_ACTION_KEY, m_playerSp);
        m_isMoving = false;
    }
}

void Monster::onPlayerMoveBefore(Vector2 &pos)
{
    //检查即将移动的位置是否会发生碰撞
    Vector2 dt = pos - m_playerSp->getPosition();
    Rect t = m_playerRect;
    t.move(dt);

    DebugerAssert(m_scene, "场景不能为空");

    if (!m_scene->isCollision(m_id, t))
    {
        return;
    }

    // DebugInfor("---------------------");

    //不改变位置
    pos = m_playerSp->getPosition();

    //发生碰撞，进入站立状态
    this->getMonsterMachine()->changeState(new MigrationState);
}

void Monster::onPlayerMoveAfter(const Vector2 &old_pos, const Vector2 &now_pos)
{
    if (old_pos == now_pos)
    {
        return;
    }

    //更新shape
    auto dt = now_pos - old_pos;
    m_playerRect.move(dt);
    m_skillLine.move(dt);
    Vector2 p = m_hpProgressBar->getPosition() + dt;
    m_hpProgressBar->move(p);
    m_hurtNumberLabel->move(p);

    //更新在场景中的位置
    if (m_scene)
    {
        m_scene->modifyRectById(m_id, m_playerRect);
    }
}

Monster::~Monster()
{
    GameWorld::getInstance()->getEventManager()->removeListener(m_debugEventHandle);

    if (m_monsterDate)
    {
        delete m_monsterDate;
    }
}

void Monster::playMoveAnimation()
{
    auto action = Animate::create(m_animationMove);
    action->setName(MOVE_ANIMATION_NAME);
    m_playerSp->runAction(action->convertToActionSharedPtr());
}

void Monster::stopMoveAnimation()
{
    m_playerSp->stopActionByName(MOVE_ANIMATION_NAME);
}

void Monster::playAttackAnimation()
{
    AnimateSharedPtr action = Animate::create(m_animationAttack);
    ActionCallFunctionSharedPtr fun = ActionCallFunction::create(std::bind(&Monster::onAttackFinish, this));

    //序列动画
    auto seq = ActionSequence::create(std::dynamic_pointer_cast<ActionTime>(action), std::dynamic_pointer_cast<ActionTime>(fun));
    seq->setName(ATTACK_ANIMATION_NAME);

    m_playerSp->runAction(seq->convertToActionSharedPtr());

    int id = s_skill_audio_id;
    GameWorld::getInstance()->getScheduler()->addSchedulerTaskDelay([id]()
                                                                    { AudioManager::getInstance()->playAudio(id); },
                                                                    std::to_string((unsigned int)this), 300);
}

void Monster::stopAttackAnimation()
{
    m_playerSp->stopActionByName(ATTACK_ANIMATION_NAME);
    GameWorld::getInstance()->getScheduler()->removeSchedulerTask(std::to_string((unsigned int)this));
}

void Monster::playerDamageAnimation()
{
    AnimateSharedPtr animation = Animate::create(m_animationDamage);
    ActionCallFunctionSharedPtr func = ActionCallFunction::create([this]()
                                                                  { m_isPlayDamageAnimation = false; });

    auto action = ActionSequence::create(std::dynamic_pointer_cast<ActionTime>(animation), std::dynamic_pointer_cast<ActionTime>(func));
    action->setName(DAMAGE_ANIMATION_NAME);
    m_playerSp->runAction(action->convertToActionSharedPtr());

    m_isPlayDamageAnimation = true;
}

void Monster::stopDamageAnimation()
{
    m_isPlayDamageAnimation = false;
    m_playerSp->stopActionByName(DAMAGE_ANIMATION_NAME);
}

void Monster::playDeathAnimation()
{
    m_playerSp->runAction(Animate::create(m_animationDeath));
}
